package com.tongfusoft.document.doc.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tongfusoft.da.template.service.impl.DataTemplateServiceImpl;
import com.tongfusoft.document.doc.service.IAdvancedSearchService;
import com.tongfusoft.document.dto.ConditionDto;
import com.tongfusoft.document.dto.QueryDto;
import com.tongfusoft.document.entity.CustomSearches;
import com.tongfusoft.document.entity.MetadataDefine;
import com.tongfusoft.document.entity.Users;
import com.tongfusoft.document.manager.metadata.service.IMetadataService;
import com.tongfusoft.utils.JsonUtils;
import com.tongfusoft.utils.UIDGeneratorService;

@Service("advancedSearchService")
public class AdvancedSearchServiceImpl extends DataTemplateServiceImpl implements IAdvancedSearchService {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	public IMetadataService metaDataManagerService;

	/**
	 * 查询字段分别有文档系统属性和自定义元数据
	 */
	@Override
	public QueryDto analysis(String queryTa) {

		
		
		if (logger.isDebugEnabled()) {

			logger.debug("queryTa Text:" + queryTa);
		}
		Map<String, String> map = JsonUtils.getMap4Json(queryTa);
		List<MetadataDefine> metaDataList = this.metaDataManagerService.getIsEnableMeta();

		Iterator<Map.Entry<String, String>> entries = map.entrySet().iterator();
		List<ConditionDto> conditionList = new ArrayList();
		// 系统元素数据解析
		while (entries.hasNext()) {
			ConditionDto cdto = new ConditionDto();
			Map.Entry<String, String> entry = entries.next();
			if (StringUtils.contains(entry.getKey(), "search_")) {

				if (!StringUtils.contains(entry.getKey(), "_notation")) {
					if (StringUtils.isNotEmpty(map.get(entry.getKey()))) {
						cdto.setFieldName(StringUtils.replace(entry.getKey(), "search_", ""));
						cdto.setValue(map.get(entry.getKey()));
						cdto.setFieldType("String");
						cdto.setNotation(map.get(entry.getKey() + "_notation"));
						cdto.setMetaDataType("system");
						conditionList.add(cdto);
					}
				}
			}
		}
		if (logger.isDebugEnabled()) {

			logger.debug("System MetaDta Search Text:" + JsonUtils.getJsonString4List(conditionList));
		}
		// 定义元数据解析
		for (MetadataDefine metadata : metaDataList) {

			if (metadata.getMetadataType().equals("date")) {
				// 处理日期类型的条件
				if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag() + "_start"))) {
					ConditionDto cdto_start = new ConditionDto();
					cdto_start.setFieldName(metadata.getMetadataTag()+ "_start");
					cdto_start.setValue(map.get(metadata.getMetadataTag() + "_start"));
					cdto_start.setFieldType("date");
					cdto_start.setNotation("ge");
					cdto_start.setMetaDataType("custom");
					conditionList.add(cdto_start);

				}
				if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag() + "_end"))) {

					ConditionDto cdto_end = new ConditionDto();
					cdto_end.setFieldName(metadata.getMetadataTag()+ "_end");
					cdto_end.setValue(map.get(metadata.getMetadataTag() + "_end"));
					cdto_end.setFieldType("date");
					cdto_end.setNotation("le");
					cdto_end.setMetaDataType("custom");
					conditionList.add(cdto_end);
				}
			} else if (metadata.getMetadataType().equals("number")) {
				// 处理数字类型
				// 如果是数字输入框，处理起始值，结束值
				if (metadata.getImportMode().equals("1")) {
					if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag() + "_start"))) {
						ConditionDto cdto_start = new ConditionDto();
						cdto_start.setFieldName(metadata.getMetadataTag() + "_start");
						cdto_start.setValue(map.get(metadata.getMetadataTag() + "_start"));
						cdto_start.setFieldType("number");
						cdto_start.setNotation("ge");
						cdto_start.setMetaDataType("custom");
						conditionList.add(cdto_start);

					}
					if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag() + "_end"))) {

						ConditionDto cdto_end = new ConditionDto();
						cdto_end.setFieldName(metadata.getMetadataTag()+ "_end");
						cdto_end.setValue(map.get(metadata.getMetadataTag() + "_end"));
						cdto_end.setFieldType("number");
						cdto_end.setNotation("le");
						cdto_end.setMetaDataType("custom");
						conditionList.add(cdto_end);
					}

				} else {

					if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag()))) {
						ConditionDto cdto = new ConditionDto();
						cdto.setFieldName(metadata.getMetadataTag());
						cdto.setValue(map.get(metadata.getMetadataTag()));
						cdto.setFieldType("number");
						cdto.setMetaDataType("custom");

						cdto.setNotation(map.get(metadata.getMetadataTag() + "_notation"));
						conditionList.add(cdto);

					}

				}

			} else {
				// 处理字符
				if (StringUtils.isNotEmpty(map.get(metadata.getMetadataTag()))) {
					ConditionDto cdto = new ConditionDto();
					cdto.setFieldName(metadata.getMetadataTag());
					cdto.setValue(map.get(metadata.getMetadataTag()));
					cdto.setFieldType("String");
					cdto.setMetaDataType("custom");
					cdto.setNotation(map.get(metadata.getMetadataTag() + "_notation"));
					conditionList.add(cdto);

				}
			}

		}

		if (logger.isDebugEnabled()) {

			logger.debug("Custom MetaDta Search Text:" + JsonUtils.getJsonString4List(conditionList));
		}
		QueryDto query = new QueryDto();

		query.setMainPage(listPageMap().get("mainPage_" + map.get("sourcePage")));
		query.setMainPageKey(listPageMap().get("mainPageKey_" + map.get("sourcePage")));
		query.setQueryJson(JsonUtils.getJsonString4List(conditionList));
		return query;
	}

	@Override
	public String generateSQl(String queryText) {

		StringBuffer sql = new StringBuffer();
		List<ConditionDto> cList = JsonUtils.getList4Json(queryText, ConditionDto.class);
		for (ConditionDto dto : cList) {

			if (StringUtils.isNotEmpty(dto.getValue())) {
				String fieldType = dto.getFieldType();

				switch (fieldType) {
				case "date":
					this.appendDate(dto, sql);
					break;
				case "String":
					this.appendString(dto, sql);
					break;
				case "number":
					this.appendNumber(dto, sql);
					break;
				default:
					break;
				}

			}
		}
		return sql.toString();
	}

	private StringBuffer appendDate(ConditionDto dto, StringBuffer sql) {
		if (StringUtils.contains(dto.getFieldName(), "_start")) {

			if (dto.getMetaDataType().equals("system")) {
				sql.append(" and d.").append(this.camel2Underline(StringUtils.replace(dto.getFieldName(), "_start", ""))).append(" >= ")
						.append("STR_TO_DATE('").append(dto.getValue()).append("'),'%Y-%m-%d %H:%i')");

			} else {

				sql.append(" and ").append("STR_TO_DATE(cast(d.DOC_METADATA ->> '$.").append(StringUtils.replace(dto.getFieldName(), "_start", "")).append("' as char),'%Y-%m-%d %H:%i') >= ")
				   .append("STR_TO_DATE('").append(dto.getValue()).append("','%Y-%m-%d %H:%i')");
				
			}

		} else {

			if (dto.getMetaDataType().equals("system")) {
				sql.append(" and d.").append(this.camel2Underline(StringUtils.replace(dto.getFieldName(), "_end", ""))).append(" <= ")
						.append("STR_TO_DATE('").append(dto.getValue()).append("'),'%Y-%m-%d %H:%i')");

			} else {

				sql.append(" and ").append("STR_TO_DATE(cast(d.DOC_METADATA ->> '$.").append(StringUtils.replace(dto.getFieldName(), "_end", "")).append("' as char),'%Y-%m-%d %H:%i') <= ")
				   .append("STR_TO_DATE('").append(dto.getValue()).append("','%Y-%m-%d %H:%i')");
			}

		}

		return sql;

	}

	private StringBuffer appendNumber(ConditionDto dto, StringBuffer sql) {

		String[] strs = StringUtils.split(dto.getValue(), ".");
		int len = 0;
		for (String str : strs) {

			len = len + str.length();

		}
		if (StringUtils.contains(dto.getFieldName(), "_start")) {

			if (dto.getMetaDataType().equals("system")) {
				

				sql.append(" and d.").append(this.camel2Underline(StringUtils.replace(dto.getFieldName(), "_start", ""))).append(" >= ")
						.append(dto.getValue());

			} else {

				sql.append(" and ").append(" cast(d.DOC_METADATA ->> '$.").append(StringUtils.replace(dto.getFieldName(), "_start", "")).append("' as DECIMAL(").append(len).append(",").append(strs.length > 1 ? (strs[1].length()) : 0).append(")) >= ")
				   .append(dto.getValue());
			}

		} else if (StringUtils.contains(dto.getFieldName(), "_end")) {
			if (dto.getMetaDataType().equals("system")) {
				
				sql.append(" and d.").append(this.camel2Underline(StringUtils.replace(dto.getFieldName(), "_end", ""))).append(" <= ")
				.append(dto.getValue());
				
				

			} else {

				sql.append(" and ").append(" cast(d.DOC_METADATA ->> '$.").append(StringUtils.replace(dto.getFieldName(), "_end", "")).append("' as DECIMAL(").append(len).append(",").append(strs.length > 1 ? (strs[1].length()) : 0).append(")) <= ")
				   .append(dto.getValue());
			}

		} else {

			if (dto.getMetaDataType().equals("system")) {
				// sql.append(" and
				// ").append(StringUtils.replace(dto.getFieldName(), "_start",
				// "")).append(" <=
				// ").append("STR_TO_DATE('").append(dto.getValue()).append("'),'%Y-%m-%d
				// %H:%i')");

			} else {

				sql.append(" and ").append(" cast(d.DOC_METADATA ->> '$.").append(StringUtils.replace(dto.getFieldName(), "_end", "")).append("' as DECIMAL(").append(len).append(",").append(strs.length > 1 ? (strs[1].length()) : 0).append(")) ");
				 

				if (dto.getNotation().equals("eq")) {
					sql.append(" = ");

				} else {
					sql.append(" <> ");

				}
				  sql.append(dto.getValue());
			}

		}

		return sql;

	}

	private StringBuffer appendString(ConditionDto dto, StringBuffer sql) {

		if (dto.getMetaDataType().equals("system")) {
			sql.append(" and d.").append(this.camel2Underline(dto.getFieldName()));

			if (dto.getNotation().equals("eq")) {

				sql.append(" = ").append("'").append(dto.getValue()).append("'");

			} else if (dto.getNotation().equals("neq")) {

				sql.append(" <> ").append("'").append(dto.getValue()).append("'");
			} else {

				sql.append(" like ").append("'%").append(dto.getValue()).append("%'");
			}

		} else {

			sql.append(" and ").append("cast(d.DOC_METADATA ->> '$.").append(dto.getFieldName()).append("' as char)");

			if (dto.getNotation().equals("eq")) {

				sql.append(" = ").append("'").append(dto.getValue()).append("'");

			} else if (dto.getNotation().equals("neq")) {

				sql.append(" <> ").append("'").append(dto.getValue()).append("'");
			} else {

				sql.append(" like ").append("'%").append(dto.getValue()).append("%'");
			}
		}

		return sql;

	}
	
	 private  String camel2Underline(String line){
	        if(line==null||"".equals(line)){
	            return "";
	        }
	        line=String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
	        StringBuffer sb=new StringBuffer();
	        Pattern pattern=Pattern.compile("[A-Z]([a-z\\d]+)?");
	        Matcher matcher=pattern.matcher(line);
	        while(matcher.find()){
	            String word=matcher.group();
	            sb.append(word.toUpperCase());
	            sb.append(matcher.end()==line.length()?"":"_");
	        }
	        return sb.toString();
	    }

	private Map<String, String> listPageMap() {

		Map<String, String> pageInfo = new HashMap();
		pageInfo.put("mainPageKey_mydoc", "myDocList");
		pageInfo.put("mainPage_mydoc", "doc/myDocList");
		return pageInfo;

	}

	@Override
	public CustomSearches saveSearchTa(CustomSearches cs,Users user) {
		
		cs.setCreatedBy(user.getUserId());
		cs.setStatus("1");
		cs.setCsId(UIDGeneratorService.getUUID());
		cs.setLastUpdBy(user.getUserId());
		cs.setCreatedDate(new Timestamp(new Date().getTime()));
		cs.setLastUpdDate(new Timestamp(new Date().getTime()));
		super.insert("saveQueryCriteria", cs);
		return cs;
	}

	@Override
	public void updateSearchTa(CustomSearches cs, Users user) {

		cs.setLastUpdBy(user.getUserId());
		cs.setLastUpdDate(new Timestamp(new Date().getTime()));
		super.insert("updateQueryCriteria", cs);
	}

	@Override
	public void deleteSearchTa(CustomSearches cs, Users user) {
		cs.setLastUpdBy(user.getUserId());
		cs.setLastUpdDate(new Timestamp(new Date().getTime()));
		super.insert("deleteQueryCriteria", cs);		
	}

	@Override
	public CustomSearches getDetail(String csId, Users user) {

		CustomSearches cs = new CustomSearches();
		cs.setCreatedBy(user.getUserId());
		cs.setCsId(csId);
		return (CustomSearches)this.selectOne("queryCriteriaList", cs);
	}

	@Override
	public List<CustomSearches> queryCriteriaList(Users user) {
		
		CustomSearches cs = new CustomSearches();
		cs.setCreatedBy(user.getUserId());
		
		return this.selectList("queryCriteriaList", cs);
	}

}
